package com.thx.resource.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.thx.common.spring.BeanFactory;
import com.thx.common.struts2.CurdAction;
import com.thx.common.util.ComplexPropertyPreFilter;
import com.thx.common.web.ActionResult;
import com.thx.common.web.WebConstant;
import com.thx.log.LogUtil;
import com.thx.privilege.PriviManager;
import com.thx.privilege.PriviManagerFactory;
import com.thx.privilege.PriviObj;
import com.thx.resource.model.Resource;
import com.thx.resource.service.ResourceManager;
import com.thx.role.model.Role;
import com.thx.role.service.RoleManager;
import com.thx.user.model.User;
import com.thx.user.service.UserManager;

@Namespace("/sys")
@Action(value = "resource", results = {
    @Result(name = "list", location = "/pages/system/resource/list.jsp"),
    @Result(name = "view", location = "/pages/system/resource/detail.jsp"),
    @Result(name = "input", location = "/pages/system/resource/input.jsp"),
    @Result(name = "menuHtml", location = "/pages/system/resource/menu.jsp"),
    @Result(name = "json", type = "json", params = {"root", "result"}),
    @Result(name = "menu", type = "json", params = {"root", "resourcesJson"})})
@Controller
@Scope("prototype")
public class ResourceAction extends CurdAction<Resource> {

  private static final long serialVersionUID = 1L;

  protected static final String DATATYPE_JSON = "json";
  protected static final String DATATYPE_HTML = "html";

  protected String parentId;

  protected boolean hasChildren;

  protected String resourcesJson;

  protected String dataType;
  protected List<String> resIds = new ArrayList<String>();
  protected List<String> restypes = new ArrayList<String>();

  @Autowired
  protected ResourceManager resourceMgr;

  @Autowired
  private UserManager userManager;

  @Autowired
  private RoleManager roleManager;

  public String searchMenus() {
    // --1.当前登陆者的拥有的菜单
    List<PriviObj> pos = getPrivisByCurrentUser();
    // --2.将PriviObj转化成resource
    List<Resource> resources = Convert2Resource(pos, parentId);
    // --3.转化成json
    ComplexPropertyPreFilter filter = new ComplexPropertyPreFilter();
    filter.setIncludes(new HashMap<Class<?>, String[]>() {

      private static final long serialVersionUID = -8411128674046835592L;

      {
        put(Resource.class, new String[] {"name", "url", "target", "smallIcon", "accessible",
            "childrenResources"});
      }
    });
    resourcesJson = com.alibaba.fastjson.JSON.toJSONString(resources, filter);
    return "menu";
  }

  public String getMenu() {
    if (StringUtils.isBlank(dataType) || DATATYPE_HTML.equals(dataType)) {
      // --1.当前登陆者的拥有的菜单
      List<PriviObj> pos = getPrivisByCurrentUser();
      // --2.将PriviObj转化成resource
      list = Convert2Resource(pos, parentId);
      return "menuHtml";
    } else {
      return searchMenus();
    }
  }

  protected List<Resource> Convert2Resource(List<PriviObj> pos, String pId) {
    List<Resource> result = new ArrayList<Resource>();
    if (StringUtils.isBlank(pId)) {
      result = resourceMgr.getByParentId(null);
      getPriviMenuResources(result, pos);
      for (Resource r : result) {
        getPriviChildrenRes(r, pos);
      }
    } else {
      if (!hasChildren) {
        result = resourceMgr.getByParentId(pId);
        getPriviMenuResources(result, pos);
      } else {
        result = resourceMgr.getByParentId(pId);
        getPriviMenuResources(result, pos);
        for (Resource r : result) {
          getPriviChildrenRes(r, pos);
        }
      }

    }
    return result;
  }

  protected void getPriviChildrenRes(Resource resource, List<PriviObj> pos) {
    List<Resource> children = resourceMgr.getByParentId(resource.getResourceId());
    if (children != null && children.size() > 0) {
      getPriviMenuResources(children, pos);
      resource.setChildrenResources(children);
      for (Resource child : children) {
        getPriviChildrenRes(child, pos);
      }
    }
  }

  protected void getPriviMenuResources(List<Resource> result, List<PriviObj> pos) {
    List<Resource> remove = new ArrayList<Resource>();
    for (Resource re : result) {
      if (!hasResource(pos, re)) {
        remove.add(re);
      } else if (!"1".equals(re.getMenuAble())) {
        remove.add(re);
      }
    }
    result.removeAll(remove);
  }

  protected boolean hasResource(List<PriviObj> pos, Resource res) {
    for (PriviObj po : pos) {
      if (po.getObjId().equals(res.getResourceId()))
        return true;
    }
    return false;
  }

  protected List<PriviObj> getPrivisByCurrentUser() {
    User user = (User) getSession().getAttribute(WebConstant.KEY_USER);
    List<PriviObj> result = new ArrayList<PriviObj>();
    if (user != null) {
      PriviManager priMgr = PriviManagerFactory.getpPriviManager();
      result = priMgr.getUserPrivileges(user.getUserId(), PriviObj.PRIVITYPE_MENU);
      List<Role> roles = user.getRoleList();

      if (roles == null) {
        roles = roleManager.findByUserId(user.getUserId());
        if(roles==null)roles=new ArrayList<Role>();
        user.setRoleList(roles);
      }

      Iterator<Role> it = roles.iterator();
      while (it.hasNext()) {
        Role role = it.next();
        List<PriviObj> rolePrivis = priMgr.getRolePrivileges(role.getRoleId(), PriviObj.PRIVITYPE_MENU);
        result.addAll(rolePrivis);
      }
    }
    return result;
  }

  public String getParentId() {
    return parentId;
  }

  public void setParentId(String parentId) {
    this.parentId = parentId;
  }

  public String getResourcesJson() {
    return resourcesJson;
  }

  public void setResourcesJson(String resourcesJson) {
    this.resourcesJson = resourcesJson;
  }

  public boolean isHasChildren() {
    return hasChildren;
  }

  public void setHasChildren(boolean hasChildren) {
    this.hasChildren = hasChildren;
  }

  @Override
  protected void doList() throws Exception {
    List<Resource> res = resourceMgr.getByParentId(null);
    list = new ArrayList<Resource>();
    int index = 0;
    for (Resource resource : res) {
      index = addList(index, resource);
      resource.setIndex(index);
      resource.setGridClass("treegrid-" + index);
      index = addChildrenToList(resource, list, index);
    }
    logger.debug("获取资源列表", list);
  }

  private int addList(int index, Resource resource) {
    list.add(resource);
    return ++index;
  }

  protected int addChildrenToList(Resource resource, List<Resource> list, int index) {
    List<Resource> children = resourceMgr.getByParentId(resource.getResourceId());
    if (children != null && children.size() > 0) {
      for (Resource child : children) {
        index = addList(index, child);
        child.setGridClass("treegrid-" + index + " treegrid-parent-" + resource.getIndex());
        child.setIndex(index);
        index = addChildrenToList(child, list, index);
      }
    }
    return index;
  }

  @Override
  protected void doView() throws Exception {
    if (StringUtils.isNotBlank(id)) {
      entity = resourceMgr.get(id);
      if (entity == null) {
        setResult(ActionResult.FAIL, "要查看的记录不存在！！！");
      }
    } else {
      setResult(ActionResult.FAIL, "服务器异常！");
    }

  }

  protected void doInput() throws Exception {
    if (StringUtils.isNotBlank(id)) {
      entity = resourceMgr.get(id);
      if (entity == null) {
        setResult(ActionResult.FAIL, "要修改的记录不存在！！！");
      }
    }
  }

  @Override
  protected void doSave() throws Exception {
    try {
      // --TODO 图标
      if (StringUtils.isBlank(id)) {
        int orderSeq = 0;
        if (StringUtils.isBlank(entity.getParentId())) {
          entity.setParentId(null);
          List<Resource> children = resourceMgr.getByParentId(null);
          if (children != null && children.size() > 0)
            orderSeq = children.size();
        } else {
          List<Resource> children = resourceMgr.getByParentId(entity.getParentId());
          if (children != null && children.size() > 0)
            orderSeq = children.size();
        }
        entity.setOrderSeq(orderSeq);
        entity.setName(StringUtils.strip(entity.getName()));
        entity.setCode(StringUtils.strip(entity.getCode()));
        entity.setUrl(StringUtils.strip(entity.getUrl()));
        entity.setDescription(StringUtils.strip(entity.getDescription()));
        resourceMgr.save(entity);
        setResult(ActionResult.SUCCESS, "添加成功！");
        LogUtil.log("资源模块", LogUtil.ACTION_ADD, LogUtil.RESULT_SUCCESS, "新增资源");
      } else {
        Resource r = resourceMgr.get(id);
        r.setName(StringUtils.strip(entity.getName()));
        r.setCode(StringUtils.strip(entity.getCode()));
        r.setUrl(StringUtils.strip(entity.getUrl()));
        r.setAccessible(entity.getAccessible());
        r.setDescription(StringUtils.strip(entity.getDescription()));
        r.setMenuAble(entity.getMenuAble());
        if (StringUtils.isBlank(entity.getParentId())) {
          entity.setParentId(null);
        }
        r.setOrderSeq(entity.getOrderSeq());
        r.setParentId(entity.getParentId());
        r.setTarget(entity.getTarget());
        resourceMgr.save(r);
        setResult(ActionResult.SUCCESS, "修改成功！");
        LogUtil.log("资源模块", LogUtil.ACTION_UPDATE, LogUtil.RESULT_SUCCESS, "修改资源");
      }
    } catch (Exception e) {
      if (StringUtils.isBlank(id)) {
        setResult(ActionResult.FAIL, "添加失败！");
      } else {
        setResult(ActionResult.FAIL, "修改失败！");
      }
      logger.error(e.getMessage(), e);
    }
  }

  /**
   * 验证code是否存在
   */
  public void checkCode() {
    try {
      Resource r = resourceMgr.findByCode(entity.getCode());
      if (r == null) {
        writeJson("true");
      } else {
        if (StringUtils.isNotBlank(id) && id.equals(r.getResourceId())) {
          // --修改时用户名和原来的可以保持一致
          writeJson("true");
        } else {
          writeJson("false");
        }

      }

    } catch (Exception e) {
      setResult(ActionResult.FAIL, "服务器异常！");
    }
  }

  /**
   * 验证url是否存在
   */
  public void checkUrl() {
    try {
      Resource r = resourceMgr.findByUrl(entity.getUrl());
      if (r == null) {
        writeJson("true");
      } else {
        if (StringUtils.isNotBlank(id) && id.equals(r.getResourceId())) {
          // --修改时用户名和原来的可以保持一致
          writeJson("true");
        } else {
          writeJson("false");
        }

      }

    } catch (Exception e) {
      setResult(ActionResult.FAIL, "服务器异常！");
    }
  }

  @Override
  protected void doDelete() throws Exception {
    try {
      if (StringUtils.isNotBlank(id)) {
        Resource src = resourceMgr.get(id);
        resIds.add(src.getResourceId());
        restypes.add(src.getPriviType());
        deleteRes(id);
        if (resIds.size() > 0) {
          PriviManager primgr = PriviManagerFactory.getpPriviManager();
          for (int i = 0; i < resIds.size(); i++) {
            primgr.delPriUser(resIds.get(i), restypes.get(i));
            primgr.delPriRole(resIds.get(i), restypes.get(i));
          }
        }
        setResult(ActionResult.SUCCESS, "删除成功！");
        LogUtil.log("资源模块", LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除资源");
      } else {
        setResult(ActionResult.FAIL, "ID不能为空！");
      }
    } catch (Exception e) {
      System.out.println(e);
      setResult(ActionResult.FAIL, "服务器异常！");
    }
  }

  protected void deleteRes(String id) {
    List<Resource> res = resourceMgr.getAll();
    for (Resource r : res) {
      if (StringUtils.isNotBlank(r.getParentId()) && r.getParentId().equals(id)) {
        resIds.add(r.getResourceId());
        restypes.add(r.getPriviType());
        deleteRes(r.getResourceId());
      }
    }
    resourceMgr.delete(id);
  }

  @Override
  protected void doDelMulti() throws Exception {

    if (delId != null && delId.length > 0) {
      delId = delId[0].split(",");
      for (String id : delId) {
        Resource src = resourceMgr.get(id);
        resIds.add(src.getResourceId());
        restypes.add(src.getPriviType());
        deleteRes(id);
        if (resIds.size() > 0) {
          PriviManager primgr = PriviManagerFactory.getpPriviManager();
          for (int i = 0; i < resIds.size(); i++) {
            primgr.delPriUser(resIds.get(i), restypes.get(i));
            primgr.delPriRole(resIds.get(i), restypes.get(i));
          }
        }
        resIds.clear();
        restypes.clear();
      }
      setResult(ActionResult.SUCCESS, "删除成功！！！");
      LogUtil.log("资源模块", LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除资源");
    } else {
      setResult(ActionResult.FAIL, "服务器异常！");
    }
  }

  public String getDataType() {
    return dataType;
  }

  public void setDataType(String dataType) {
    this.dataType = dataType;
  }
}
